package ME2AND;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.Paint.Align;
import android.graphics.Paint.Cap;
import android.graphics.Paint.Join;
import android.graphics.Paint.Style;

/** Auto generated stub code from a class file */
public class Graphics {

  public static final int HCENTER = 1;
  public static final int VCENTER = 2;
  public static final int LEFT = 4;
  public static final int RIGHT = 8;
  public static final int TOP = 16;
  public static final int BOTTOM = 32;
  public static final int BASELINE = 64;
  public static final int SOLID = 0;
  public static final int DOTTED = 1;
  
  private android.graphics.Bitmap map;
  private android.graphics.Canvas g;
  private android.graphics.Paint p;
  private Font font;
  private Rect srcRect;
  private Rect destRect;
  private Rect bounds;
  private Matrix m;
  
  private int clipX;
  private int clipY;
  private int clipW;
  private int clipH;
  private int transX;
  private int transY;
  private float[] vals = new float[9];
  private int stroke;
  private int baseW;
  private int baseH;
  
  private static float xScale = 1f;
  private static float yScale = 1f;
  private static boolean isNotScaled = true;
  
  public Graphics(android.graphics.Canvas canvas) {
  	this(canvas, canvas.getWidth(), canvas.getHeight());
  }
  
  public Graphics(android.graphics.Canvas canvas, int width, int height) {

  	p = new Paint();
  	g = canvas;
  	
  	baseW = width;
  	baseH = height;
  	
  	srcRect = new Rect();
  	destRect = new Rect();

  	m = g.getMatrix();
  	bounds = g.getClipBounds();
  	stroke = SOLID;
  	setFont(Font.getDefaultFont());
  	_resetClip();

  }
  
  public Graphics(Bitmap dest) {
  	map = dest;
  	
  	p = new Paint(0);
  	g = new Canvas(map);
  	baseW = map.getWidth();
  	baseH = map.getHeight();
  	srcRect = new Rect();
  	destRect = new Rect();
  	m = g.getMatrix();
  	stroke = SOLID;
  	setFont(Font.getDefaultFont());
  	_resetClip();
  }
  
  public static void setScale(float xScale, float yScale) {
	  Graphics.xScale = xScale;
	  Graphics.yScale = yScale;
	  if(xScale != 1f || yScale != 1f) {
		  isNotScaled = false;
	  } else {
		  isNotScaled = true;
	  }
  }
  
  public static float getXScale() {
	  return xScale;
  }
  
  public static float getYScale() {
	  return yScale;
  }
  
  public void _resetClip() {
  	clipX = 0;
  	clipY = 0;
  	clipW = baseW;
  	clipH = baseH;
  	transX = 0;
  	transY = 0;
  	bounds = new Rect(0, 0, clipW, clipH);
  	g.clipRect(bounds, Region.Op.REPLACE);
  }
  
  public void _loadClip() {
  	
  	g.getClipBounds(bounds);
  	clipX = (int) ((bounds.left) / xScale);
  	clipY = (int) ((bounds.top) / yScale);
  	clipH = (int) ((bounds.bottom - bounds.top) / xScale);
  	clipW = (int) ((bounds.right - bounds.left) / yScale);
  	
  	g.getMatrix(m);
  	m.getValues(vals);
  	transX = (int) (vals[Matrix.MTRANS_X] / xScale);
  	transY = (int) (vals[Matrix.MTRANS_Y] / yScale);
  	//makeRect(recta, clipX, clipY, clipW, clipH);
  	//Log.w("warn", "clip " + clipX + ", " + clipY + ", " + clipW + ", " + clipH + ", "  + transX + ", " + transY);
  	
  }
  
  private Rect makeRect(Rect rect, int xp, int yp, int width, int height, float xScale, float yScale) {
	 if(isNotScaled) {
		 rect.left = xp;
		 rect.right = (xp + width);
	 } else {
		 rect.left = (int) (xp * xScale);
		 rect.right = (int) ((xp + width) * xScale);
	 }
	 
	if(isNotScaled) {
		rect.top = yp;
		rect.bottom = (yp + height);
	} else {
	  	rect.top = (int) (yp * yScale);
	  	rect.bottom = (int) ((yp + height) * yScale);
	}
  	return rect;
  }
  
  private Rect makeRect(Rect rect, int xp, int yp, int width, int height) {
	rect.left = xp;
	rect.right = (xp + width);
	rect.top = yp;
	rect.bottom = (yp + height);
	return rect;
  }
  
  private Rect makeDestRect(int xp, int yp, int width, int height) {
	  return makeRect(destRect, xp, yp, width, height, xScale, yScale);
  }
  
  public void translate(int i0, int i1) {
  	g.translate(i0 * xScale, i1 * yScale);
  	_loadClip();
  }

  public int getTranslateX() {
    return transX;
  }

  public int getTranslateY() {
    return transY;
  }

  public int getColor() {
    return p.getColor();
  }

  public int getRedComponent() {
    return (p.getColor() >> 16) & 0xff;
  }

  public int getGreenComponent() {
    return (p.getColor() >> 8) & 0xff;
  }

  public int getBlueComponent() {
    return (p.getColor()) & 0xff;
  }

  public int getGrayScale() {
    return (getRedComponent() + getGreenComponent() + getBlueComponent()) / 3;
  }

  public void setColor(int red, int green, int blue) {
  	int colour = ((red & 0xff) << 16) + ((green & 0xff) << 8) + (blue & 0xff);
  	setColor(colour);
  }

  public void setColor(int colour) {
  	p.setColor(colour | 0xff000000);
  }

  public void setGrayScale(int i0) {
  	setColor(i0, i0, i0);
  }

  public Font getFont() {
	if(font == null) {
		setFont(Font.getDefaultFont());
	}
    return font;
  }

  public void setStrokeStyle(int style) {
  	stroke = style;
  }

  public int getStrokeStyle() {
    return stroke;
  }

  public void setFont(Font font) {
  	this.font = font;
  	font._loadPaint(p);
  }

  public int getClipX() {
    return clipX;
  }

  public int getClipY() {
    return clipY;
  }

  public int getClipWidth() {
    return clipW;
  }

  public int getClipHeight() {
    return clipH;
  }

  public void clipRect(int x, int y, int w, int h) {
	g.clipRect(x * xScale, y * yScale, (x + w ) * xScale, (y + h) * yScale, Region.Op.INTERSECT);
  	_loadClip();
  }

  public void setClip(int x, int y, int w, int h) {
  	g.clipRect(x * xScale, y * yScale, (x + w ) * xScale, (y + h) * yScale, Region.Op.REPLACE);
  	_loadClip();
  }

  // http://www.cs.unc.edu/~mcmillan/comp136/Lecture6/Lines.html
  public void drawLine(int x0, int y0, int x1, int y1)
  {

	//ES: looks like bresnahms is incredibly slow (50x slower?), so reverted to native.
  
  /*
      int dy = y1 - y0;
      int dx = x1 - x0;
      int stepx, stepy;

      if (dy < 0) { dy = -dy;  stepy = -1; } else { stepy = 1; }
      if (dx < 0) { dx = -dx;  stepx = -1; } else { stepx = 1; }
      dy <<= 1;                                                  // dy is now 2*dy
      dx <<= 1;                                                  // dx is now 2*dx

      
      g.drawPoint(x0, y0,p);
      if (dx > dy) {
          int fraction = dy - (dx >> 1);                         // same as 2*dy - dx
          while (x0 != x1) {
              if (fraction >= 0) {
                  y0 += stepy;
                  fraction -= dx;                                // same as fraction -= 2*dx
              }
              x0 += stepx;
              fraction += dy;                                    // same as fraction -= 2*dy
              g.drawPoint(x0, y0,p);
          }
      } else {
          int fraction = dx - (dy >> 1);
          while (y0 != y1) {
              if (fraction >= 0) {
                  x0 += stepx;
                  fraction -= dy;
              }
              y0 += stepy;
              fraction += dx;
              g.drawPoint(x0, y0,p);
          }
      }*/
	  
	  //for an explanation of the +0.5
	  p.setStrokeWidth(0);
	  p.setStrokeCap(Cap.SQUARE);
	  p.setStrokeJoin(Join.BEVEL);
	  g.drawLine(
			  (float) ((x0 * xScale)), 
			  (float) ((y0 * yScale)), 
			  (float) ((x1 * xScale)), 
			  (float) ((y1 * yScale)), 
			  p);
  }

  public void fillRect(int x, int y, int width, int height) {
	  if(width < 0 || height < 0) { return; }
	  p.setStyle(Style.FILL);
	  makeDestRect(x, y, width, height);
	  g.drawRect(destRect, p);
  }

  public void drawRect(int x, int y, int width, int height) {
	  if(width < 0 || height < 0) { return; }
	  p.setStyle(Style.STROKE);
	  makeDestRect(x, y, width, height);
	  g.drawRect(destRect, p);
  }

  public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
	  if(width < 0 || height < 0) { return; }
	  makeDestRect(x, y, width, height);
	  RectF fRect = new RectF(destRect);
	  p.setStyle(Style.STROKE);
	  g.drawRoundRect(fRect, arcWidth, arcHeight, p);
  }

  public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
	  makeDestRect(x, y, width, height);
	  RectF fRect = new RectF(destRect);
	  p.setStyle(Style.FILL);
	  g.drawRoundRect(fRect, arcWidth, arcHeight, p);
  }

  public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) {  	
	  makeDestRect(x, y, width, height);
	  RectF fRect = new RectF(destRect);
	  p.setStyle(Style.FILL);
	  g.drawArc(fRect, -startAngle, -arcAngle, true, p);
  }

  public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
	  makeDestRect(x, y, width, height);
	  RectF fRect = new RectF(destRect);
	  p.setStyle(Style.STROKE);
	  g.drawArc(fRect, -startAngle, -arcAngle, true, p);
  }

  public void drawString(String str, int x, int y, int anchor) {

  	if(font == null) {
  		setFont(Font.getDefaultFont());
  	}
  	
  	Align align;
  	if((anchor & HCENTER) > 0)  {
  		align = Align.CENTER;
  	} else if((anchor & RIGHT) > 0) {
  		align = Align.RIGHT;
  	}  else  {
  		align = Align.LEFT;
  	}
  	
  	int height = getFont().getHeight();
  	//shift anchor to top.. android draws along baseline by default
  	//TODO correct calculation for baseline position
  	//  	y += (height >> 1);
  	y += height;
  	
  	if((anchor & BOTTOM) > 0) {
		y -= height;
	} else if((anchor & (BASELINE | VCENTER)) > 0) {
		y -= (height >> 1); //back to default position
	}
    
    p.setTextAlign(align);
    p.setAntiAlias(true);
    p.setSubpixelText(true);

    g.drawText(str, x, y, p);

    p.setAntiAlias(false);
    p.setSubpixelText(false);
  }

  public void drawSubstring(String str, int offset, int length, int x, int y, int anchor) {
  	drawString(str.substring(offset, offset + length), x, y, anchor);
  }

  public void drawChar(char c, int x, int y, int anchor) {
  	drawString("" + c, x, y, anchor);
  }

  public void drawChars(char[] c1, int offset, int length, int x, int y, int anchor) {
  	String str = new String(c1);
  	drawString(str.substring(offset, offset + length), x, y, anchor);
  }

  public void fillTriangle(int x1, int y1, int x2, int y2, int x3, int y3) {

	  Path pa = new Path();
	  pa.moveTo(x1, y1);
	  pa.lineTo(x2, y2);
	  pa.lineTo(x3, y3);

	  p.setStyle(Style.FILL);
	  g.drawPath(pa, p);
  }

  public int getDisplayColor(int colour) {
    return colour;
  }

}

